//-----------------------------------------------------------------------
// <copyright file="RegEx.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Andy Reeves</author>
// <email>andyr</email>
// <date>2004-03-23</date>
// <summary>Reads in a text file and modifies the contents by searching for
// and replacing text satisfying a regular expression.
// </summary>
//-----------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.File
{
    using System;
    using System.Xml;
    using System.Globalization;
    using System.IO;
    using System.Text.RegularExpressions;
    using Microsoft.Build.Framework;

    /// <summary>
    /// Reads in a text file and modifies the contents by searching for
    /// and replacing text satisfying a regular expression pattern.
    /// 
    /// The task File.Replace can also be used to fulfill this functionality and more.
    /// This version is kept for compatibility with previous versions.
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[
    /// <File.RegEx
    ///             Path="path"
    ///             Force="force"
    ///             NewValue="newValue"
    ///             RegularExpression="regularExpression" >
    /// </File.RegEx>
    /// ]]></code>
    /// <para>where:</para>
    /// <para><i>path (Required)</i></para>
    /// <para>The full path and filename of the text file to be modified.</para>
    /// <para><i>force</i></para>
    /// <para>If set to true, this will modify the text file even if it is read-only. Set to false to ignore read-only files. Defaults to false.</para>
    /// <para><i>newValue (required)</i></para>
    /// <para>The new value for the specified attribute.</para>
    /// <para><i>regularExpression (required)</i></para>
    /// <para>The regular expression pattern to match.</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <!-- Replaces runs of white space in file1.txt with a
    ///          comma and a blank.
    ///     -->
    ///     <Target Name="Test" >
    ///         <File.RegEx
    ///             Path="C:\SourceFiles\file1.txt"
    ///             RegularExpression="\s+"
    ///             NewValue=", " />
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public class RegEx : TaskBase
    {
        private string path = String.Empty;
        private bool force = false;
        private string regularExpression = String.Empty;
        private string newValue = String.Empty;

        /// <summary>
        /// Initializes a new instance of the RegEx class.
        /// </summary>
        public RegEx()
        {
        }

        /// <summary>
        /// The full path and filename of the text file to be modified.
        /// </summary>
        /// <value>The full path and filename of the text file to be modified.</value>
        [Required]
        public string Path
        {
            get { return (this.path == null ? String.Empty : this.path); }
            set { this.path = value; }
        }         

        /// <summary>
        /// The regular expression pattern to match.
        /// </summary>
        /// <value>The regular expression pattern to match.</value>
        [Required]
        public string RegularExpression
        {
            get { return (this.regularExpression == null ? String.Empty : this.regularExpression); }
            set { this.regularExpression = value; }
        }

        /// <summary>
        /// The new value for the RegEx.
        /// </summary>
        /// <value>The new value for the RegEx.</value>
        public string NewValue
        {
            get { return (this.newValue == null ? String.Empty : this.newValue); }
            set { this.newValue = value; }
        }

        /// <summary>
        /// If set to true, this will modify the text file even if it is read-only.
        /// </summary>
        /// <value>If set to true, this will modify the text file even if it is read-only. Set to false to ignore read-only files. Defaults to false.</value>
        public bool Force
        {
            get { return this.force; }
            set { this.force = value; }
        }
        
        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            #region Execute code

            Log.LogMessageFromResources("File.RegEx", this.path);

            if (System.IO.File.Exists(this.path))
            {
                if (this.regularExpression.Length > 0)
                {
                    // Load contents into fileContents
                    FileInfo fi = new FileInfo(this.path);
                    FileAttributes originalAttributes = fi.Attributes;

                    string fileContents = string.Empty;
                    using (StreamReader textFileReader = new StreamReader(this.path))
                    {
                        fileContents = textFileReader.ReadToEnd();
                        textFileReader.Close();
                    }

                    // Replace matched values in fileContents
                    Regex regex = new Regex(this.regularExpression);
                    fileContents = regex.Replace(fileContents, this.newValue);

                    // Set file attributes so that we can overwrite if necessary
                    if (this.force)
                    {
                        fi.Attributes = FileAttributes.Normal;
                    }

                    // Write new contents to file
                    using (StreamWriter textFileWriter = new StreamWriter(this.path))
                    {
                        textFileWriter.Write(fileContents);
                        textFileWriter.Close();
                    }

                    if (this.force)
                    {
                        fi.Attributes = originalAttributes;
                    }
                }
                else
                {
                    throw new TaskException("File.RegularExpressionRequired");
                }
            }
            else
            {
                throw new TaskException("File.NotFound", this.path);
            }
            #endregion
        }
    }
}